package javaDemo.demo.day_03_ThreadOrderAccess;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description 多线程执行顺序的严格控制
 * @Author
 * @Date 2020/10/31 16:15
 * @Version 1.0
 */
public class ThreadOrderAccess {

    /**
     * 多线程之间，实现按顺序调用：A->B->C
     *
     * 三个线程启动后，要求：
     * AA打印五次，BB打印10次，CC打印15次
     * 接着
     * AA打印五次，BB打印10次，CC打印15次
     * ....
     * 循环操作10次
     * @param args
     */
    public static void main(String[] args) {

        ShareSource shareSource = new ShareSource();

        new Thread(() -> { for (int i = 0; i < 10; i++)  shareSource.print5(); },"线程A").start();
        new Thread(() -> { for (int i = 0; i < 10; i++)  shareSource.print10(); },"线程B").start();
        new Thread(() -> { for (int i = 0; i < 10; i++)  shareSource.print15(); },"线程C").start();

    }
}

/**
 * 共享资源类
 */
class ShareSource{
    private int number = 1; // 1:A   2:B   3:C
    private final Lock lock = new ReentrantLock();
    private final Condition condition1 = lock.newCondition();
    private final Condition condition2 = lock.newCondition();
    private final Condition condition3 = lock.newCondition();


    public void print5(){
        lock.lock();
        try{

            //1、判断
            while (number != 1){
                condition1.await();
            }
            //2、干活
            for (int i = 1; i <= 5; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }
            //3、通知
            number = 2;
            condition2.signal();


        } catch(Exception e){
            e.printStackTrace();
        } finally{
            lock.unlock();
        }
    }

    public void print10(){
        lock.lock();
        try{


            //1、判断
            while (number != 2){
                condition2.await();
            }
            //2、干活
            for (int i = 1; i <= 10; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }
            //3、通知
            number = 3;
            condition3.signal();


        } catch(Exception e){
            e.printStackTrace();
        } finally{
            lock.unlock();
        }
    }

    public void print15(){
        lock.lock();
        try{


            //1、判断
            while (number != 3){
                condition3.await();
            }
            //2、干活
            for (int i = 1; i <= 15; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }
            //3、通知
            number = 1;
            condition1.signal();


        } catch(Exception e){
            e.printStackTrace();
        } finally{
            lock.unlock();
        }
    }
}
